/*******************************************
 * Copyright 2007 Aphrodite Framework for javaME .
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v2.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * Email : owner@aphroditeme.dev.java.net
 * Contributors:
 *     Kent Elton - initial API and implementation
 *******************************************/

package com.aphrodite.security;

/**
 * Password generator
 * <p>
 * 
 * <pre>
 * PasswordGenerator pwdGen = new PasswordGenerator(&quot;aphrodite&quot;, &quot;test&quot;);
 * pwdGen.setLength(8);
 * String pwd = pwdGen.generate();
 * </pre>
 * 
 * </p>
 * 
 * @author kentelt
 * 
 */
public final class PasswordGenerator {
	private int LENGTH = 8;
	private final String m_label;
	private final String m_password;

	private String m_rawHash;

	/**
	 * Creates a new PasswordGenerator instance
	 * 
	 * @param label
	 *            password label
	 * @param password
	 *            sample password
	 */
	public PasswordGenerator(String label, String password) {
		m_label = label;
		m_password = password;
	}

	/**
	 * 
	 * @return a random password
	 */
	public final String generate() {
		MD5 md5 = new MD5();

		md5.Update(m_password);
		md5.Update(m_label);
		m_rawHash = new String(Base64.encode(md5.Final()));
		// Base64Coder.urlSafeEncode(md5.Final()));

		String hash = requireDigit(m_rawHash);

		return hash.substring(0, LENGTH);
	}

	/**
	 * Only here for testing purposes. Not valid unless generate has been
	 * called.
	 */
	String getRawHash() {
		return m_rawHash;
	}

	/**
	 * Generate a password that contains digits also
	 * 
	 * @param password
	 * @return
	 */
	public final String requireDigit(final String password) {
		boolean foundDigits = false;
		StringBuffer digits = new StringBuffer();
		for (int i = 0; i < password.length(); i++) {
			if (Character.isDigit(password.charAt(i))) {
				if (i < LENGTH) {
					// in this case, we already have a number, so
					// nothing for us to do.
					return password;
				} else {
					digits.append(password.charAt(i));
					foundDigits = true;
				}
			} else {
				if (foundDigits) {
					return digits.toString() + password;
				}
			}
		}
		return '1' + password;
	}

	/**
	 * 
	 * @param length
	 *            of the password to generate
	 */
	public void setLength(int length) {
		this.LENGTH = length;
	}

}
